#!/usr/bin/env python

"""
Game Baker - Main Game Designer GUI

An open source, cross platform game design system
http://code.google.com/p/game-baker

ps sorry about the state of the code for the GUI, 
it's due for a cleanup - see issue 28

"""

import sys,os
import runtime
import gobject
import game,GUI.treeview
from pygame.locals import *
from GUI import *



try:
     import pygtk
     pygtk.require("2.0")
except: pass

try:
    import gtk
    import gtk.glade
except: sys.exit(1)


def find_item_name(dic,item):
    a = [name for name in dic.keys() if dic[name] == item]
    
    if not len(a) == 1:
        return None
    else:
        return a[0]




class MainGTK:
    """Main Game Baker GUI class"""

    def __init__(self):
        
        #Set the Glade file
#        self.gladefile = "GUI/gamebaker.glade/gamebaker.glade"  
        self.gladefile = "GUI/gamebaker.glade/gamebaker.glade" 
        self.wTree = gtk.glade.XML(self.gladefile) 
        
        def show_about(widget = None):
            self.wTree.get_widget("aboutdialog1").show()

        self.treeviewhelp = GUI.treeview.treeview_helper(self.wTree.get_widget("treeview1"))

        # Define event handlers for Gtk objects
        dic = { "on_wnd_main_destroy" : gtk.main_quit ,
                "on_new1_activate" : self.new_game,
                "on_quit1_activate" : gtk.main_quit,
                "on_open1_activate" : self.open_file,
                "on_save1_activate" : self.save_file,
                "on_save_as1_activate" : self.save_file_as,
                "on_about1_activate" : show_about,
                "on_refresh1_activate":self.treeviewhelp.update_item_list,
                "on_add_object1_activate":self.new_game_object,
                "on_add_workstate1_activate":self.new_workstate,
                "on_play1_activate":self.run_game,
                "on_btn_run_clicked":self.run_game,
                "on_treeview1_row_activated":self.open_properties,
                "on_btn_new_item_clicked":self.add_item_choice,
                "on_wnd_new_item_destroy_event":hide_window,
                "on_wnd_new_item_destroy_event":hide_window,
                "wnd_delete_event":hide_window,
                "on_cbxworkstateevents_changed":self.change_event_selected,
                "on_close1_activate":self.closegame,
                "btn_save_event":self.save_event,
                "on_btn_undo_event_changes":self.change_event_selected,
                "on_btn_workstate_ok":self.workstate_ok,
                "on_btn_gamescreen_colourpicker_clicked":self.choose_background_colour_gamescreen,
                "on_btn_gamescreen_ok_clicked":self.gamescreen_ok,
                "on_btn_obj_ok_clicked":self.object_ok,
                "on_gameproperties1_activate":self.show_game_properties,
                "on_mnu_import_sprite_activate":self.import_sprite,
                "on_btn_game_ok_clicked":self.game_properties_ok,
                "on_btn_workstate_cancel":self.workstate_cancel,
                "on_btn_new_gamescreen":self.new_game_screen,
                "on_btn_add_obj_to_gamescreen_clicked":self.add_obj_to_gamescreen,
                "show_new_event_popup":self.show_new_event_popup,
                "new_init_event":(lambda x:self.add_new_event(runtime.EVENT_INIT)),
                "new_iter_event":(lambda x:self.add_new_event(runtime.EVENT_ITERATION)),
                "new_offscreen_event":(lambda x:self.add_new_event(runtime.EVENT_OFFSCREEN)),
                "new_keydown_left_event":(lambda x:self.add_new_event(runtime.EVENT_KEYDOWN * K_LEFT)),
                "new_keydown_right_event":(lambda x:self.add_new_event(runtime.EVENT_KEYDOWN * K_RIGHT)),
                "new_keydown_up_event":(lambda x:self.add_new_event(runtime.EVENT_KEYDOWN * K_UP)),
                "new_keydown_down_event":(lambda x:self.add_new_event(runtime.EVENT_KEYDOWN * K_DOWN)),

                "new_keyup_left_event":(lambda x:self.add_new_event(runtime.EVENT_KEYUP * K_LEFT)),
                "new_keyup_right_event":(lambda x:self.add_new_event(runtime.EVENT_KEYUP * K_RIGHT)),
                "new_keyup_up_event":(lambda x:self.add_new_event(runtime.EVENT_KEYUP * K_UP)),
                "new_keyup_down_event":(lambda x:self.add_new_event(runtime.EVENT_KEYUP * K_DOWN)),
                "new_l_mouse_up_event":(lambda x:self.add_new_event(runtime.EVENT_LMOUSEUP )),
                "new_r_mouse_up_event":(lambda x:self.add_new_event(runtime.EVENT_RMOUSEUP )),
                "on_delete1_activate":self.delete_item

                }

        # Tell gtk to use these event handlers
        self.wTree.signal_autoconnect(dic)

        self.game = None

        self.selectedworkstate=None

        # Blank filename as filename is unknown
        self.filename = ""


        # Extra initialisation of combo boxes
        def init_combo_box(name):
        	cb = self.wTree.get_widget(name)
        	cell = gtk.CellRendererText()
        	cb.pack_start(cell,True)
        	cb.add_attribute(cell,'text',0)
        	
        init_combo_box("cbxworkstateevents")
        init_combo_box("cbx_workstateoptns")
        init_combo_box("cbx_gamescreen_object_options")
        


        #treeview_gamescreen_objects
        treeview = self.wTree.get_widget("treeview_gamescreen_objects")
        column = gtk.TreeViewColumn("Name"
                    , gtk.CellRendererText(),
                    text=1) # position of column
        treeview.append_column(column)
        column = gtk.TreeViewColumn("Type"
                    , gtk.CellRendererText(),
                    text=2) # position of column
        treeview.append_column(column)




    def add_new_event(self,event):

        if not self.selectedworkstate.actions.has_key(event):
            self.selectedworkstate.actions[event] = "\n"
            cb = self.wTree.get_widget("cbxworkstateevents")
            model = cb.get_model()
            model.append([event_names.get(event,str(event)),event])
            cb.set_model(model)
            self.change_event_selected()



    def show_new_event_popup(self,widget=None,event=None):
        self.wTree.get_widget("popup_events").popup(None, None, None
        		, event.button, event.time)

    def show_game_properties(self,widget=None):
        """Show the Game Properties window"""
        self.wTree.get_widget("wnd_game").show()
        self.wTree.get_widget("txt_game_name").set_text(str(self.game.title))
        self.wTree.get_widget("txt_initial_gamescreen").set_text(str(self.game.startscreen))

        text = self.wTree.get_widget("textview_load_events")
        textbuffer = text.get_buffer()
        try:
            textbuffer.set_text(self.game.initcode)
        except: pass

        # TODO : 
        # Populate the selection box

    def new_game(self,widget=None):
        self.game = game.Game("")
        self.show_game_properties()
        self.treeviewhelp.clear()
        self.treeviewhelp.populate_from_game(self.game)


    def game_properties_ok(self,widget=None):
        self.game.title = self.wTree.get_widget("txt_game_name").get_text()
        self.wTree.get_widget("wnd_main").set_title(self.game.title + " - Game Baker")
        self.wTree.get_widget("wnd_game").hide()
        self.game.startscreen = self.wTree.get_widget("txt_initial_gamescreen").get_text() 
        if not self.game.gamescreens.has_key(self.game.startscreen):    
            self.game.gamescreens[self.game.startscreen] = self.game.gamescreen((800,600),self.game.startscreen)
        text = self.wTree.get_widget("textview_load_events")
        textbuffer = text.get_buffer()
        startiter, enditer = textbuffer.get_bounds()
        self.game.initcode = textbuffer.get_text(startiter,enditer)
        self.treeviewhelp.update_item_list()

    def object_ok(self,widget=None):
        oldname = find_item_name(self.game.gameobjects,self.selectedobject)
        newname = self.wTree.get_widget("txt_obj_name").get_text()
        if not oldname == newname:
            self.game.gameobjects[newname] = self.selectedobject
            del self.game.gameobjects[oldname]
        self.treeviewhelp.update_item_list()

        if not self.wTree.get_widget("txt_obj_sprite").get_text()=="":
            self.selectedobject.sprite = self.wTree.get_widget("txt_obj_sprite").get_text()

        else:
            self.selectedobject.sprite = None

        # Change Workstate
        cb = self.wTree.get_widget("cbx_workstateoptns")
        try:
            self.selectedobject.baseworkstate= str(cb.get_model()[cb.get_active()][0])
        except: pass

        self.wTree.get_widget("wnd_Object").hide()


    def gamescreen_ok(self,widget=None):
        oldname = find_item_name(self.game.gamescreens,self.selectedgamescreen)
        newname = self.wTree.get_widget("txt_gamescreen_name").get_text()
        if not oldname == newname:
            self.game.gamescreens[newname] = self.selectedgamescreen
            del self.game.gamescreens[oldname]
            self.treeviewhelp.update_item_list()

        r = int( self.wTree.get_widget("txt_gamescreen_bg_r").get_text() )
        g = int( self.wTree.get_widget("txt_gamescreen_bg_g").get_text() )
        b = int( self.wTree.get_widget("txt_gamescreen_bg_b").get_text() )
        self.selectedgamescreen.color  = (r,g,b)
        # Itterate through list and update startobjects
        treeview =  self.wTree.get_widget("treeview_gamescreen_objects")
        model = treeview.get_model()

        # Need TODO - change this so it stores a string, not a reference (in engine too)
        startobjects = [m[0] for m in model]
        self.selectedgamescreen.startobjects = startobjects


        self.wTree.get_widget("wnd_gamescreen").hide()


    def workstate_ok(self,widget=None):
        oldname = find_item_name(self.game.workstates,self.selectedworkstate)
        newname = self.wTree.get_widget("txt_workstate_name").get_text()
        if not oldname == newname:
            self.game.workstates[newname] = self.selectedworkstate
            del self.game.workstates[oldname]
        # Still have to update treeview
        self.treeviewhelp.update_item_list()

        self.wTree.get_widget("wnd_workstate").hide()

    def workstate_cancel(self,widget=None):
        self.wTree.get_widget("wnd_workstate").hide()


    def change_event_selected(self,widget=None):
        cb = self.wTree.get_widget("cbxworkstateevents")
        active = cb.get_active()
        model = cb.get_model()

        text = self.wTree.get_widget("text_event_script")
        textbuffer = text.get_buffer()

        textbuffer.set_text(self.selectedworkstate.actions.get(int(model[active][1]),""))

    def save_event(self,widget=None):
        cb = self.wTree.get_widget("cbxworkstateevents")
        active = cb.get_active()
        model = cb.get_model()

        text = self.wTree.get_widget("text_event_script")
        textbuffer = text.get_buffer()
        #print model,active,self,self.selectedworkstate
        startiter, enditer = textbuffer.get_bounds()
        script = textbuffer.get_text(startiter,enditer)
        self.selectedworkstate.actions[int(model[active][1])] = script

    def choose_background_colour_gamescreen(self,widget=None):
        # Show Colour Selection
        colorseldlg = gtk.ColorSelectionDialog("Background Colour")

        # Get the ColorSelection widget
        colorsel = colorseldlg.colorsel
        colorsel.set_has_opacity_control(False)

        try:
            colour = self.selectedgamescreen.color
        except:
            colour = (255,255,255)

        gdkcolour = gtk.gdk.Color()

        gdkcolour.red = colour[0] *65535 / 255
        gdkcolour.green = colour[1]*65535 / 255
        gdkcolour.blue = colour[2]*65535 / 255
        colorsel.set_current_color(gdkcolour)

        self.gdkcolour = gdkcolour
        def change_colour(widget = None):
            self.gdkcolour = colorsel.get_current_color()

        colorsel.connect("color_changed", change_colour)

        response = colorseldlg.run()
        gdkcolour = self.gdkcolour

        if response -- gtk.RESPONSE_OK:
            print gdkcolour, gdkcolour.red
            self.wTree.get_widget("txt_gamescreen_bg_r").set_text(str(gdkcolour.red * 255 / 65535))
            self.wTree.get_widget("txt_gamescreen_bg_g").set_text(str(gdkcolour.green* 255 / 65535))
            self.wTree.get_widget("txt_gamescreen_bg_b").set_text(str(gdkcolour.blue* 255 / 65535))
        else:
            pass

        colorseldlg.hide()



    def delete_item(self,widget=None,prop2 = None, prop3 = None):
        selection = self.wTree.get_widget("treeview1").get_selection()
        model,sel_iter = selection.get_selected()

        obj = model.get_value(sel_iter, 0)

        # To Do: Pop up a "Are you sure" dialogue
        try:
            if obj.objtype == "Gameobject":
                
                pass
            elif obj.objtype == "Sprite":
                pass
            elif obj.objtype == "Gamescreen":
                pass
            elif obj.objtype == "Workstate":
                pass
        except:
            pass



    def open_properties(self,widget=None,prop2 = None, prop3 = None):
        selection = self.wTree.get_widget("treeview1").get_selection()
        model,sel_iter = selection.get_selected()

        obj = model.get_value(sel_iter, 0)
        try:
            if obj.objtype == "Gameobject":
                self.wTree.get_widget("wnd_Object").show()
                # Set Name
                self.wTree.get_widget("txt_obj_name").set_text(find_item_name(self.game.gameobjects,obj))

                if not obj.sprite is None:
                    self.wTree.get_widget("txt_obj_sprite").set_text(obj.sprite)

                model = gtk.ListStore(str)
                for ws in self.game.workstates.keys():
                    model.append([ws])
                cb = self.wTree.get_widget("cbx_workstateoptns")
                cb.set_model(model)
                try:
                    cb.set_active(self.game.workstates.keys().index(obj.baseworkstate))
                except: pass
                self.selectedobject = obj
                print self.selectedobject


            elif obj.objtype == "Sprite":
                pass

            elif obj.objtype == "Gamescreen":
                self.wTree.get_widget("wnd_gamescreen").show()
                self.wTree.get_widget("txt_gamescreen_name").set_text(find_item_name(self.game.gamescreens,obj))
                try: 
                    color = obj.color
                except:
                    color=(255,255,255)

                self.wTree.get_widget("txt_gamescreen_bg_r").set_text( str(color[0]) )
                self.wTree.get_widget("txt_gamescreen_bg_g").set_text( str(color[1]) )
                self.wTree.get_widget("txt_gamescreen_bg_b").set_text( str(color[2]) )

                # Show List of options for objects
                model = gtk.ListStore(str)
                for go in self.game.gameobjects.keys():
                    model.append([go])
                cb = self.wTree.get_widget("cbx_gamescreen_object_options")
                cb.set_model(model)

                self.selectedgamescreen = obj


                treeview =  self.wTree.get_widget("treeview_gamescreen_objects")
                treestore = gtk.TreeStore(gobject.TYPE_PYOBJECT, gobject.TYPE_STRING,gobject.TYPE_STRING)

                for go in obj.startobjects:
                    insert_iter = treestore.append(None, [go,go.name,go.name])
                print obj.startobjects
                treeview.set_model(treestore)


            elif obj.objtype == "Workstate":
                self.wTree.get_widget("wnd_workstate").show()
                self.wTree.get_widget("txt_workstate_name").set_text(find_item_name(self.game.workstates,obj))

                cb = self.wTree.get_widget("cbxworkstateevents")

                model = gtk.ListStore(str,int)

                model.clear()
                for event in obj.actions.keys():
                    model.append([event_names.get(event,str(event)),event])

                cb.set_model(model)

                cb.set_active(0)
                self.selectedworkstate = obj
                self.change_event_selected()
                

        except Exception, inst:
            print inst

    def add_obj_to_gamescreen(self,widget=None):
        # Get current selection
        cb =  self.wTree.get_widget("cbx_gamescreen_object_options")
        active = cb.get_active()
        model = cb.get_model()
        obj_name = model[active][0]

        # Now add this to the list        
        treeview =  self.wTree.get_widget("treeview_gamescreen_objects")
        model = treeview.get_model()
        obj = self.game.gameobjects[obj_name]
        model.append(None,[obj,obj_name,obj_name])

    def add_item_choice(self,widget=None):
        self.wTree.get_widget("wnd_new_item").show()

    def import_sprite(self,widget=None):
        file_open = gtk.FileChooserDialog(title="Open Game File"
                                , action=gtk.FILE_CHOOSER_ACTION_OPEN
                                , buttons=(gtk.STOCK_CANCEL
                                                , gtk.RESPONSE_CANCEL
                                                , gtk.STOCK_OPEN
                                                , gtk.RESPONSE_OK))
        """Create and add the filter"""
        filter = gtk.FileFilter()
        filter.set_name("Game Baker Sprite")
        filter.add_pattern("*.gbs")
        file_open.add_filter(filter)
        """Create and add the 'all files' filter"""
        filter = gtk.FileFilter()
        filter.set_name("All files")
        filter.add_pattern("*")
        file_open.add_filter(filter)
        filename = ""
        if file_open.run() == gtk.RESPONSE_OK:
                filename = file_open.get_filename()
        file_open.destroy()
 
        if not filename == "":
            import gbfileio
            newsprite = gbfileio.loadgame(filename,typ="sprite")
            name = ""
            try:
                name = newsprite.name
            except: pass
            if name == "":
                i = 1
                while self.game.sprites.has_key("ImportedSprite%d"%i):
                    i+=1
                name = "ImportedSprite%d"%i
            self.game.sprites[name] = newsprite
            self.treeviewhelp.update_item_list()
        

    def open_file(self,widget = None):
        file_open = gtk.FileChooserDialog(title="Open Game File"
                                , action=gtk.FILE_CHOOSER_ACTION_OPEN
                                , buttons=(gtk.STOCK_CANCEL
                                                , gtk.RESPONSE_CANCEL
                                                , gtk.STOCK_OPEN
                                                , gtk.RESPONSE_OK))
        """Create and add the filter"""
        filter = gtk.FileFilter()
        filter.set_name("Game Baker Games")
        filter.add_pattern("*.gb")
        file_open.add_filter(filter)
        """Create and add the 'all files' filter"""
        filter = gtk.FileFilter()
        filter.set_name("All files")
        filter.add_pattern("*")
        file_open.add_filter(filter)
        filename = ""
        if file_open.run() == gtk.RESPONSE_OK:
                filename = file_open.get_filename()
        file_open.destroy()
	
        if not filename == "":
            import gbfileio
            self.game = gbfileio.loadgame(filename)
            self.treeviewhelp.clear()
            self.treeviewhelp.populate_from_game(self.game)
            self.filename = filename
            os.chdir(os.path.split(filename)[0])
            self.wTree.get_widget("wnd_main").set_title(self.game.title + " - Game Baker")

    def closegame(self,widget=None):
        """Close the currently open game"""
        self.treeviewhelp.clear()
        self.game=None
        self.wTree.get_widget("wnd_main").set_title("- Game Baker")

    def save_file(self,widget = None):
        if self.filename == "":
            self.save_file_as(widget)
        else:
            import gbfileio
            gbfileio.savegame(self.filename,self.game)

    def save_file_as(self,widget = None):
        file_save = gtk.FileChooserDialog(title="Save Game File"
                                , action=gtk.FILE_CHOOSER_ACTION_SAVE
                                , buttons=(gtk.STOCK_CANCEL
                                    , gtk.RESPONSE_CANCEL
                                    , gtk.STOCK_SAVE
                                    , gtk.RESPONSE_OK))
        """Create and add the filter"""
        filter = gtk.FileFilter()
        filter.set_name("Game Baker Game")
        filter.add_pattern("*.gb")
        file_save.add_filter(filter)
        """Create and add the 'all files' filter"""
        filter = gtk.FileFilter()
        filter.set_name("All files")
        filter.add_pattern("*")
        file_save.add_filter(filter)
        filename = ""
        if file_save.run() == gtk.RESPONSE_OK:
            filename = file_save.get_filename()
            if not filename[-3:] == ".gb":
                filename = filename + ".gb"
        file_save.destroy()

        if not filename == "":
            import gbfileio
            gbfileio.savegame(filename,self.game)
            os.chdir(os.path.split(filename)[0])

    def new_game_object(self,widget = None):
        count = 1
        while self.game.gameobjects.has_key("GameObject%d"%count):
            count+=1
        mytestGameObject = self.game.gameobject("GameObject%d"%count)
        # Hide options window if it's shown
        self.wTree.get_widget("wnd_new_item").hide()
        self.treeviewhelp.update_item_list()
        
    def new_workstate(self,widget = None):
        count = 1
        while self.game.workstates.has_key("Workstate%d"%count):
            count+=1
        mytestWorkState = self.game.workstate("Workstate%d"%count)
        #Hide options window if it's shown
        self.wTree.get_widget("wnd_new_item").hide()
        self.treeviewhelp.update_item_list()

    def new_game_screen(self,widget=None):
        count = 1
        while self.game.gamescreens.has_key("GameScreen%d"%count):
            count+=1
        mytestGameScreen = self.game.gamescreen((800,600),"GameScreen%d"%count)
        #Hide options window if it's shown
        self.wTree.get_widget("wnd_new_item").hide()    
        self.treeviewhelp.update_item_list()    

    def run_game(self,widget = None):
        
        runtime.run_game(self.game)






if __name__ == "__main__":
    h = MainGTK()
    gtk.main()
